﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Xml.Linq;
using Rxx.Labs.Properties;
using Rxx.Parsers.Linq;

namespace Rxx.Labs.Parsers.Interactive
{
	[DisplayName("XML Schema")]
	[Description("Parses an XML string against a basic XML schema defined as a Context-Sensitive Grammar (CSG).")]
	public sealed class XmlSchemaLab : BaseConsoleLab
	{
		protected override void Main()
		{
			TraceLine(Instructions.WaitForCompletion);

			var xml = @"
<root>
	<vehicles>
		<car make=""We Get U There"" model=""Toy"" />
		<plane />
		<boat>
			<!-- Typically found on water -->
		</boat>
	</vehicles>
	<equipment>
		<tire>
			Round things on a car.
		</tire>
		<wing>
			Long things on a plane.
		</wing>
		<sail>
			Tall things on a boat.
		</sail>
	</equipment>
</root>";

			// In Silverlight, the IEnumerable<T> interface is not covariant on T, thus casting is required.
			IEnumerable<XElement> parsed = xml.ParseXml(parser =>
				from next in parser
				let text = parser.Text.Cast<char, XText, XObject>()
				let elementsWithText = parser.Element(text).OneOrMore().Select(x => x.Cast<XObject>())
				select parser.Element("root",
								parser.Element("vehicles",
									parser.Element("car", 
										new[]
										{ 
											parser.Attribute("model"), 
											parser.Attribute("make")
										})
										.Cast<char, XElement, XObject>(),
									parser.Element("plane").Cast<char, XElement, XObject>(),
									parser.Element("boat").Cast<char, XElement, XObject>())
									.Cast<char, XElement, XObject>(),
								parser.Element("equipment",
									elementsWithText)
									.Cast<char, XElement, XObject>()));

			parsed.ForEach(ConsoleOutput);
		}
	}
}